import "./array";
import observe from "./observe";
import { Watcher } from "./Watcher";
 
let obj = {
  a: {
    b: {
      c: 1
    }
  },
  arr: [1, 2, 3],
  f: 2
}
// 1. 对obj对象进行数据劫持
// 每一个需要响应式的数据都会有自己的dep，所以要在defineReactive中定义
// 步骤1：在defineReactive中创建dep对象，用来保存Dep对象，
// 步骤2：在get中收集依赖，调用dep的depend去添加watcher
// 步骤3：在set中通知更新，通知dep所有的watcher (对于数组，得在重写的变异数组里面再添加notify)
observe(obj)


// 2. 定义Dep对象：专门用来管理watcher，dep和watcher是一对多的关系
// 定义两个函数
// depend：添加watcher
// notify：通知所有watcher执行更新函数
// ./Dep.js
// src/images/6-对象的dep.png
console.log(obj);


// 3. 定义Watcher类
// ./Watcher.js
// 这部分比较难理解，Watcher会和数据绑定的比较多

// 现在有一个场景：obj.f 在页面{{obj.f}}渲染需要用到；在computed：computedF: () => obj.f * 100；也需要用到
// 那么，obj.f就有的observer.dep.subs 就有两个watcher，分别用到上面的两种作用

// 我需要创建两个watcher，一个是渲染watcher，一个是计算watcher

new Watcher(obj, 'f', (newVal, oldVal) => {
  console.log('f发生变化，页面去渲染',newVal);
})
// 控制台打印
// 创建Watcher, id= 1
// ****** watcher来拿数据啦
// （说明：创建watcher，在obj.f的set方法中添加到dep中）

new Watcher(obj, 'f', (newVal, oldVal) => {
  console.log('f发生变化，computedF值为',newVal * 100);
})
// 控制台打印
// 创建Watcher, id= 2
// ****** watcher来拿数据啦
// （说明：创建watcher，在obj.f的set方法中添加到dep中）

obj.f = 10
// 控制台打印
// ====== dep 通知 watcher 更新     （说明）调用了obj.f的set方法
// ****** watcher来拿数据啦         （说明）watcherId=1 执行update，执行回调
// f发生变化，页面去渲染 10
// ****** watcher来拿数据啦         （说明）watcherId=2 执行update，执行回调
// f发生变化，computedF值为 1000

new Watcher(obj, 'arr', (newVal, oldVal) => {
  console.log('数组', newVal, oldVal);
})
obj.arr = []




// 实现响应式
// vue的双向绑定原理基于 数据劫持 和 发布-订阅模式
// ../util/obj-reactive 和 ../util/array-reactive 主要是数据劫持的原理
// ../util/reactive 是发布订阅的实现原理

// （1）数据劫持：vue2基于Object.defineProperty()，vue3基于ES6的Proxy
// （2）发布-订阅模式：
//     vue为每个响应式数据创建一个依赖收集器（Dep）

// 什么是Dep？
// dependency collection 负责管理和收集 响应式数据的观察者（Watcher），
// 并在数据变化时通知观察者更新
// 执行步骤：
// （1）当创建一个响应式对象时，会遍历对象的所有属性，并为每个属性创建一个 Dep 实例。
// （2）当读取一个响应式属性时，会将当前的 Watcher 实例添加到该属性的 Dep 实例中。
// （3）当修改一个响应式属性时，会触发该属性的 setter，在 setter 中通知 Dep 实例更新。

// 什么是Watcher？
// 负责监听dep的响应式数据的变化通知，去执行页面更新

// dep和watcher是如何合作的？
// （1）初始化渲染时，会创建一个watcher实例，通常是渲染watcher
// （2）执行过程中会访问响应式数据的属性的getter
// （3）getter中dep去添加当前活跃的这个watcher，实现依赖收集
// （4）往后数据变化时，触发setter，就会通知订阅的watcher去更新页面

// 总结：
// 数据变化 → 触发 setter → 通知 watcher → 更新视图
// 视图输入 → 触发事件 → 更新数据 → 触发 setter → 通知 watcher → 更新视图


